Semantik Web  •  Hafta 08

Java ile OWL API — I

Neden API gerekli, hangi OWL elemanları programlanabilir, alerji ontolojisinin sıfırdan kodla kurulması

Lisansüstü Semantik Web Dersi  •  CMPE 583

Hafta 08  •  Kazanımlar

Bu hafta sonunda

  • OWL API'nin mimarisini (manager, data factory, ontology) açıklayabileceksiniz.
  • Her OWL elemanının API karşılığını bulabileceksiniz.
  • Alerji ontolojisini sıfırdan kodla kurabileceksiniz.
  • Aksiyom ekleme, silme, arama ve kaydetme işlemlerini yapabileceksiniz.
  • Değişiklik yönetimi ve hata ayıklama tekniklerini uygulayabileceksiniz.

01

Ödev 7'nin Çözümü

BMI + risk kuralı ve kural sırası.

Çözüm 7.1 — ObeseAtRisk kuralı

Person(?p) ^ hasBMI(?p, ?b) ^ swrlb:greaterThan(?b, 30.0) ^ Effected_Allergen(?p, ?f) -> ObeseAtRisk(?p)
  • S4'ten önce çalışamaz — hasBMI henüz yoktur; motor sırayı kendi bulur.
  • Tetiklenen: TC_004 (BMI 33.43, Soy_Lecitin → Egg).
  • OWL ile yazılabilir mi? Kısmen: veri aralığı + kısıt ile evet, ama hasBMI'yi üretmek için kural şart.
ObeseAtRisk = [TC_004]

02

Neden OWL API?

Protégé yeter mi? Nerede yetmez?

Protégé nerede yetmez?

SenaryoProtégéOWL API
10.000 ürünü içe almakElle imkânsızDöngüyle dakikalar
Gece güncellenen katalogİnsan gerekirZamanlanmış iş
Web servisinden risk sorgusuMümkün değilServis arka ucu
Birim testi ile doğrulamaYokJUnit
Sürüm kontrolüne uygun üretimElle kaydetmeKod = tek doğru kaynak
Kural sonucunu raporlamaEkrandan okumaJSON / PDF üretimi

Protégé tasarım aracıdır; OWL API üretim aracıdır. İkisi birbirini dışlamaz.

Neden düz RDF kütüphanesi değil?

Jena / RDF4J

Üçlü düzeyinde çalışır. Bir kısıt yazmak için blank node zincirini elle kurmanız gerekir.

6–8 triple elle + blank node yönetimi

OWL API

Aksiyom düzeyinde çalışır. Kısıt tek nesnedir; serileştirme API'nin işidir.

df.getOWLObjectSomeValuesFrom( contain, additives)

Ayrıca OWL API, reasoner arayüzünü (OWLReasoner) standartlaştırır: HermiT, Pellet, JFact aynı kodla değiştirilir.

OWL API mimarisi

OWLOntologyManagerYükleme, kaydetme, değişiklik uygulama
OWLDataFactoryVarlık ve aksiyom üretimi
OWLOntologyAksiyom kümesi (sıra yok)
OWLReasonerÇıkarım, tutarlılık
OWLOntologyManager man = OWLManager.createOWLOntologyManager(); OWLDataFactory df = man.getOWLDataFactory(); OWLOntology ont = man.createOntology( IRI.create("http://EMU/AllergyOntology"));

Ontoloji bir aksiyom kümesidir

  • Sıra yoktur: aynı aksiyomları farklı sırada eklemek aynı ontolojiyi verir.
  • Tekrar yoktur: aynı aksiyomu iki kez eklemek sayıyı artırmaz.
  • Varlıklar (sınıf, özellik, birey) kendi başına ontolojiye ait değildir; onları aksiyomlar taşır.
  • Bu yüzden yeni bir sınıf "yaratmak" için DeclarationAxiom eklenir.
En sık yapılan hata: df.getOWLClass(...) çağırıp sınıfın ontolojiye eklendiğini sanmak. O çağrı yalnızca bir referans üretir.

Hangi OWL elemanı programlanabilir?

OWL elemanıAPI karşılığı
ClassOWLClass + OWLDeclarationAxiom
SubClassOfOWLSubClassOfAxiom
EquivalentClassesOWLEquivalentClassesAxiom
DisjointClassesOWLDisjointClassesAxiom
ObjectPropertyOWLObjectProperty + domain/range aksiyomları
DataPropertyOWLDataProperty
NamedIndividualOWLNamedIndividual + ClassAssertionAxiom

Element haritası — devam

OWL elemanıAPI karşılığı
someValuesFromgetOWLObjectSomeValuesFrom
allValuesFromgetOWLObjectAllValuesFrom
hasValuegetOWLObjectHasValue
min / max / exactlygetOWLObjectMinCardinality …
intersectionOf / unionOf / notgetOWLObjectIntersectionOf / UnionOf / ComplementOf
subPropertyOfOWLSubObjectPropertyOfAxiom
sameAs / differentFromOWLSameIndividualAxiom / DifferentIndividualsAxiom
HasKeyOWLHasKeyAxiom
SWRL kuralıSWRLRule
Annotation (label, comment)OWLAnnotationAssertionAxiom

API tip hiyerarşisi: her şey bir OWLObject

OWLObject ├── OWLEntity (adı olan varlık) │ ├── OWLClass │ ├── OWLObjectProperty │ ├── OWLDataProperty │ ├── OWLNamedIndividual │ ├── OWLDatatype │ └── OWLAnnotationProperty ├── OWLClassExpression (sınıf ifadesi) │ ├── OWLClass │ ├── OWLObjectSomeValuesFrom │ ├── OWLObjectIntersectionOf … └── OWLAxiom (ifade / aksiyom) ├── OWLSubClassOfAxiom ├── OWLClassAssertionAxiom …
  • OWLEntity: IRI'si olan varlık. Tek başına anlam taşımaz.
  • OWLClassExpression: sınıf ya da anonim sınıf ifadesi. OWLClass ikisinin de altındadır.
  • OWLAxiom: ontolojiye eklenebilen tek şey.
  • Bütün nesneler değişmezdir (immutable): bir aksiyomu düzenlemek yerine silip yenisini eklersiniz.

Bu hiyerarşiyi bilmek, hangi metodun ne döndürdüğünü tahmin etmenizi sağlar — JavaDoc'a bakmadan.

Varlık üretmek ≠ ontolojiye eklemek

Yalnızca referans

OWLClass c = df.getOWLClass( IRI.create(NS + "Vegan")); // ontolojide HICBIR SEY yok ont.getAxiomCount(); // degismedi

Gerçek ekleme

man.addAxiom(ont, df.getOWLDeclarationAxiom(c)); // artik ontolojide gorunur ont.getAxiomCount(); // +1

Data factory bir fabrikadır, depo değildir. Aynı IRI için çağırdığınız her getOWLClass aynı nesneyi verir; ontolojiyi değiştiren tek şey addAxiom'dur.

OWL 2 profilleri ve API ile denetimi

ProfilAmacıAlerji projesine uygun mu
OWL 2 ELÇok büyük taksonomiler (tıp)Hayır — only ve sayı kısıtı yok
OWL 2 QLVeritabanı üstü sorguHayır — çıkarım sınırlı
OWL 2 RLKural motoru ile ölçeklemeKısmen
OWL 2 DLTam ifade gücü, karar verilebilirEvet — projenin profili
OWL2DLProfile profile = new OWL2DLProfile(); OWLProfileReport report = profile.checkOntology(ont); System.out.println("DL uyumlu mu? " + report.isInProfile()); report.getViolations().forEach(System.out::println);

Kural eklemek ontolojiyi DL dışına çıkarmaz; SWRL ayrı bir katmandır ve DL-safe kısıtla güvence altına alınır.

İçe alma (import) ve closure

// Servis ontolojisi alerji ontolojisini // ice alir man.applyChange(new AddImport(serviceOnt, df.getOWLImportsDeclaration( IRI.create("http://EMU/AllergyOntology")))); // Yerel dosya eslemesi (internet gerekmez) man.getIRIMappers().add( new AutoIRIMapper(new File("."), true)); // Ice alinanlarla birlikte oku ont.getAxioms(Imports.INCLUDED);
  • Imports.EXCLUDED: yalnızca bu ontolojinin aksiyomları (varsayılan).
  • Imports.INCLUDED: içe alınan bütün ontolojiler dahil.
  • Reasoner daima closure üzerinde çalışır — içe alınanları görür.
  • AutoIRIMapper, uzak IRI'leri yerel dosyalara eşler; çevrimdışı çalışmayı sağlar.

Değişiklik dinleyicisi: denetim izi

man.addOntologyChangeListener(changes -> { for (OWLOntologyChange ch : changes) { System.out.println((ch.isAddAxiom() ? "EKLENDI: " : "SILINDI: ") + ch.getAxiom()); } }); // Bu andan sonra her degisiklik loglanir man.addAxiom(ont, df.getOWLDeclarationAxiom(cls("Vegan")));

Gıda güvenliği gibi alanlarda "bu aksiyomu kim, ne zaman ekledi" sorusu denetim gerekliliğidir. Listener, Hafta 01'deki Trust katmanının pratik karşılığıdır.

Serileştirme formatları ve seçim

Format sınıfıÇıktıNe zaman
RDFXMLDocumentFormatRDF/XMLProtégé uyumu, projenin varsayılanı
TurtleDocumentFormatTurtleİnsan okuması, kod incelemesi
FunctionalSyntaxDocumentFormatFunctionalAksiyom yapısını görmek
ManchesterSyntaxDocumentFormatManchesterKısıtları okumak
OWLXMLDocumentFormatOWL/XMLXML araç zinciri
// Ayni ontoloji, iki formatta man.saveOntology(ont, new TurtleDocumentFormat(), IRI.create(new File("allergy.ttl").toURI())); man.saveOntology(ont, new FunctionalSyntaxDocumentFormat(), IRI.create(new File("allergy.ofn").toURI()));

Aksiyom kümesi aynıdır; yalnızca yazım değişir. Sürüm kontrolünde Turtle veya Functional, diff okunabilirliği için tercih edilir.

03

Ortam Kurulumu

Maven, NetBeans ve sürüm uyumu.

pom.xml — 1: derleyici ve OWL API

<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependency> <groupId>net.sourceforge.owlapi</groupId> <artifactId>owlapi-distribution</artifactId> <version>4.5.29</version> </dependency>
  • 1.8: SWRLAPI Java 8 ile en güvenli çalışır.
  • owlapi-distribution hepsi bir arada paket: API + ayrıştırıcılar + yazıcılar.
  • Daha ince paketleme isterseniz owlapi-api + owlapi-rio ayrı alınır.
  • 4.x dalı Protégé 5.6 ve SWRLAPI 2.x ile uyumludur.

pom.xml — 2: reasoner ve kural motoru

<dependency> <!-- HermiT --> <groupId>net.sourceforge.owlapi</groupId> <artifactId>org.semanticweb.hermit</artifactId> <version>1.4.5.519</version> </dependency> <dependency> <!-- SWRL + Drools --> <groupId>edu.stanford.swrl</groupId> <artifactId>swrlapi-drools-engine</artifactId> <version>2.1.2</version> </dependency>
  • HermiT sürüm numarasının sonundaki .519 hangi OWL API dalına derlendiğini söyler.
  • SWRLAPI, Drools'u kendi getirir — ayrıca eklemeyin.
  • Çakışma denetimi: mvn dependency:tree.
  • Kural: bütün proje tek OWL API dalına sabitlenir.

NoSuchMethodError alıyorsanız neredeyse her zaman neden budur.

NetBeans proje yapısı

AllergyReasoner/ ├── pom.xml ├── ALLERGY_FIXED.owl └── src/main/java/edu/emu/allergy/ ├── Main.java ├── OntologyBuilder.java ├── OntologyGateway.java └── RiskReport.java
  • OWL dosyası proje kökünde: new File("ALLERGY_FIXED.owl") çalışır.
  • Kaynak içine koyarsanız getResourceAsStream kullanın.
  • Paket adı IRI ile aynı olmak zorunda değildir.

04

Ontolojiyi Sıfırdan Kurmak

Alerji ontolojisi, satır satır kodla.

Adım 1a — Builder sınıfının alanları

public class OntologyBuilder { static final String NS = "http://EMU/AllergyOntology#"; private final OWLOntologyManager man = OWLManager.createOWLOntologyManager(); private final OWLDataFactory df = man.getOWLDataFactory(); private final OWLOntology ont; }
  • Üç alan: manager, data factory, ontology.
  • NS sonundaki # kritiktir — eksikse bütün IRI'ler yanlış olur ve hata alınmaz.
  • Data factory manager'dan alınır; ayrıca üretilmez.

Adım 1b — Yardımcı metotlar

public OntologyBuilder() throws Exception { ont = man.createOntology( IRI.create("http://EMU/AllergyOntology")); } private OWLClass cls(String n) { return df.getOWLClass(IRI.create(NS + n)); } private OWLObjectProperty op(String n) { … } private OWLDataProperty dp(String n) { … } private OWLNamedIndividual ind(String n) { … } private void add(OWLAxiom ax) { man.addAxiom(ont, ax); }
  • Ontoloji IRI'sinde # yoktur; namespace'te vardır.
  • Dört kısayol, kodun geri kalanını okunur tutar.
  • add() tek giriş noktasıdır — log veya doğrulama eklemek kolaylaşır.

Bu altı satırlık altyapı, sonraki 100 satırı yarıya indirir.

Adım 2a — Sınıfları bildir

String[] tops = {"Person", "Product", "FoodAdditives", "Allergy"}; for (String c : tops) add(df.getOWLDeclarationAxiom(cls(c)));
  • cls(c) yardımcısı IRI'yi kurar: NS + "Person".
  • DeclarationAxiom sınıfın var olduğunu bildirir.
  • Bu olmadan sınıf yalnızca başka bir aksiyomda geçtiğinde görünür.
  • Protégé karşılığı: sınıf ağacına yeni düğüm eklemek.

4 aksiyom eklendi.

Adım 2b — Hiyerarşiyi kur

// Adult ⊑ Person add(df.getOWLSubClassOfAxiom( cls("Adult"), cls("Person"))); // PersonAtRisk ⊑ Person add(df.getOWLSubClassOfAxiom( cls("PersonAtRisk"), cls("Person")));
  • İlk argüman alt sınıf, ikincisi üst sınıf.
  • Sıra ters yazılırsa hata alınmaz — anlam ters döner. En sinsi hatadır.
  • Bu iki sınıf elle doldurulmaz: üyeliği S5 ve S7 kuralları yazar.
  • Declaration ayrıca gerekmez; SubClassOf varlığı zaten ima eder.

2 aksiyom eklendi.

Adım 2c — Ayrıklığı bildir

Set<OWLClass> disjoint = new HashSet<>(); for (String c : tops) disjoint.add(cls(c)); add(df.getOWLDisjointClassesAxiom(disjoint));
  • Dört üst sınıf ikili ikili ayrık olur: bir birey aynı anda hem kişi hem ürün olamaz.
  • Bu aksiyom olmadan yanlış tip bildirimleri sessizce kabul edilir.
  • Hafta 05'teki tutarsızlık örneği (TC_009 Contain Nisin) ancak bu sayede yakalanır.
  • Protégé karşılığı: "Disjoint With" satırı.

1 aksiyom. Toplam: 4 + 2 + 1 = 7 aksiyom.

Adım 3a — Yardımcı metot: üç aksiyom bir arada

private void otp(String name, String domain, String range) { add(df.getOWLDeclarationAxiom(op(name))); add(df.getOWLObjectPropertyDomainAxiom( op(name), cls(domain))); add(df.getOWLObjectPropertyRangeAxiom( op(name), cls(range))); }
  • Her nesne özelliği üç aksiyom ister: bildirim, domain, range.
  • Yardımcı metot yazmak, 9 özellik × 3 aksiyom = 27 satırı 9 satıra indirir.
  • Hatırlatma: domain/range bir kısıt değil, çıkarım kaynağıdır (Hafta 03).

Adım 3b — Beş temel ilişki

otp("hasAllergy", "Person", "Allergy"); otp("ChooseProduct", "Person", "Product"); otp("Contain", "Product", "FoodAdditives"); otp("Triggers", "FoodAdditives", "Allergy"); otp("Effected_Allergen", "Person", "FoodAdditives");
  • İlk dördü girdi verisidir; elle bildirilir.
  • Effected_Allergen ise çıktıdır: değerini S6 kuralı yazar.
  • Risk zinciri bu beş ilişkiyle kapanır: Person → Product → FoodAdditives → Allergy → Person.

15 aksiyom eklendi.

Adım 3c — Alerjene özgü alt özellikler

for (String a : new String[]{ "Lactose","Egg","Fish","Gluten"}) { String sub = a + "_Allergen"; otp(sub, "Person", "FoodAdditives"); add(df.getOWLSubObjectPropertyOfAxiom( op(sub), op("Effected_Allergen"))); }
  • Dört özellik üretilir: Lactose_Allergen … Gluten_Allergen.
  • Hepsi Effected_Allergen altındadır.
  • Kazanç: S1–S3 alt özelliği yazar, RDFS üst özelliğe yükseltir, S7 yalnızca üst özelliğe bakar.

4 × (3+1) = 16 aksiyom. Bölüm toplamı: 31 aksiyom.

Adım 4 — Veri özellikleri

private void dtp(String name, OWLDatatype type, String domain) { add(df.getOWLDeclarationAxiom(dp(name))); add(df.getOWLDataPropertyDomainAxiom( dp(name), cls(domain))); add(df.getOWLDataPropertyRangeAxiom( dp(name), type)); }
ÖzellikTipKaynak
hasNameStringelle
hasAgeIntegerelle
hasWeightDoubleelle
hasHeightDoubleelle
hasBMIDoubleS4 kuralı
hasProductNameStringelle
dtp("hasAge", df.getIntegerOWLDatatype(), "Person"); dtp("hasWeight", df.getDoubleOWLDatatype(), "Person");

Adım 5a — Alerji bireyleri

for (String a : new String[]{ "Lactose","Egg","Fish","Gluten"}) add(df.getOWLClassAssertionAxiom( cls("Allergy"), ind(a)));
  • ClassAssertionAxiom = "bu birey şu sınıfın üyesidir".
  • Protégé karşılığı: bireyin "Types" satırı.
  • Alerjileri birey yaptık, sınıf yapmadık: yeni alerji eklemek model değişikliği gerektirmesin.

4 aksiyom.

Adım 5b — Katkı maddeleri ve tetikleme

Map<String,String> t = new LinkedHashMap<>(); t.put("Nisin", "Lactose"); t.put("Casein", "Lactose"); t.put("Soy_Lecitin", "Egg"); t.put("Sodium_Ascorbite", "Fish"); t.put("Alginic_Acid", "Gluten"); t.put("Ascorbic_Acid", null); t.put("Phospore", null);
  • null = tetikleme bilgisi bilinmiyor.
  • Açık dünya gereği bu "tetiklemez" demek değildir.
  • Bu iki katkı, projenin OWA örneğidir.

Adım 5c — Aksiyomları üret

t.forEach((additive, allergy) -> { add(df.getOWLClassAssertionAxiom( cls("FoodAdditives"), ind(additive))); if (allergy != null) add(df.getOWLObjectPropertyAssertionAxiom( op("Triggers"), ind(additive), ind(allergy))); });
  • ObjectPropertyAssertionAxiom(P, özne, nesne) — argüman sırası budur.
  • 7 tip bildirimi + 5 tetikleme = 12 aksiyom.
  • Protégé karşılığı: "Object property assertions" satırları.

Bölüm toplamı: 4 + 12 = 16 aksiyom.

Adım 6 — Ürün bireyleri

void product(String ean, String name, String... additives) { add(df.getOWLClassAssertionAxiom(cls("Product"), ind(ean))); add(df.getOWLDataPropertyAssertionAxiom( dp("hasProductName"), ind(ean), df.getOWLLiteral(name))); for (String a : additives) add(df.getOWLObjectPropertyAssertionAxiom( op("Contain"), ind(ean), ind(a))); }
product("EAN_00001","ETI Cracker", "Alginic_Acid"); product("EAN_00004","Eti Chocolate", "Ascorbic_Acid","Nisin","Soy_Lecitin");
  • String... değişken sayıda katkı alır.
  • Barkod kimliktir, ürün adı veridir — ayrı tutulur.
  • Ad için tip vermedik: getOWLLiteral(String) otomatik xsd:string üretir.

Adım 7 — Kişi bireyleri

void person(String tc, String name, int age, double w, double h, String choice, String... allergies) { add(df.getOWLClassAssertionAxiom(cls("Person"), ind(tc))); dval("hasName", tc, df.getOWLLiteral(name)); dval("hasAge", tc, df.getOWLLiteral(age)); // xsd:int dval("hasWeight",tc, df.getOWLLiteral(w)); // xsd:double dval("hasHeight",tc, df.getOWLLiteral(h)); oval("ChooseProduct", tc, choice); for (String a : allergies) oval("hasAllergy", tc, a); }
person("TC_001","Ayse",38,67.5,1.68, "EAN_00004","Lactose"); person("TC_003","MEHMET",35,93.0,1.87, "EAN_00003","Fish","Lactose");
  • int ve double parametreleri doğru literal tipini garanti eder.
  • BMI burada yoktur — S4 kuralı yazacak.
  • Bir kişi birden çok alerji taşıyabilir: String...

Literal üretimi: tip önemlidir

ÇağrıÜretilen literalS4/S5 çalışır mı
getOWLLiteral(38)"38"^^xsd:intEvet
getOWLLiteral(67.5)"67.5"^^xsd:doubleEvet
getOWLLiteral("38")"38"^^xsd:stringHayır
getOWLLiteral("Ayse")"Ayse"^^xsd:string—
getOWLLiteral("Riskli", "tr")"Riskli"@trEtiket

Java'nın aşırı yükleme (overload) seçimi burada davranışı belirler: int mi String mi verdiğinize dikkat edin.

Adım 8a — "En az bir katkı içerir"

// Product ⊑ ∃Contain.FoodAdditives OWLClassExpression expr = df.getOWLObjectSomeValuesFrom( op("Contain"), cls("FoodAdditives")); add(df.getOWLSubClassOfAxiom( cls("Product"), expr));
  • Kısıt bir anonim sınıftır: "en az bir katkı içeren şeyler".
  • Protégé'de bunu Contain some FoodAdditives diye yazarsınız.
  • API iki adımda kurar: önce ifade, sonra aksiyom.
  • RDF/XML'de blank node zinciri olur — API sizi bundan korur.

Adım 8b — İç içe kısıt: RiskyProduct

// RiskyProduct ≡ Product ⊓ ∃Contain.(∃Triggers.Allergy) OWLClassExpression inner = // ic kisit df.getOWLObjectSomeValuesFrom(op("Triggers"), cls("Allergy")); OWLClassExpression outer = // dis kisit df.getOWLObjectSomeValuesFrom(op("Contain"), inner); add(df.getOWLEquivalentClassesAxiom(cls("RiskyProduct"), df.getOWLObjectIntersectionOf(cls("Product"), outer)));
  • İfadeler içeriden dışarıya kurulur — matematikteki parantez sırası gibi.
  • EquivalentClasses seçtik: koşulu sağlayan her ürün sınıfa otomatik girer.
  • SubClassOf seçseydik hiçbir ürün sınıflandırılmazdı.

Adım 8c — Belirli bir bireye bağlanmak

// LactoseIntolerantPerson ≡ // Person ⊓ hasAllergy value Lactose add(df.getOWLEquivalentClassesAxiom( cls("LactoseIntolerantPerson"), df.getOWLObjectIntersectionOf( cls("Person"), df.getOWLObjectHasValue( op("hasAllergy"), ind("Lactose")))));
  • getOWLObjectHasValue bir bireye bağlanır.
  • getOWLObjectSomeValuesFrom ise bir sınıfa.
  • Karıştırmak boş sınıfların en yaygın nedenidir.
  • Üyeler (reasoner sonrası): TC_001, TC_002, TC_003.

Adım 9 — İki dilli etiketler

void label(OWLEntity e, String tr, String en) { add(df.getOWLAnnotationAssertionAxiom( df.getRDFSLabel(), e.getIRI(), df.getOWLLiteral(tr, "tr"))); add(df.getOWLAnnotationAssertionAxiom( df.getRDFSLabel(), e.getIRI(), df.getOWLLiteral(en, "en"))); } void buildLabels() { label(cls("PersonAtRisk"), "Riskli Kisi", "Person At Risk"); label(cls("FoodAdditives"), "Katki Maddesi", "Food Additive"); label(op("Triggers"), "tetikler", "triggers"); label(ind("Soy_Lecitin"), "Soya lesitini", "Soy Lecithin"); }

Etiketler çıkarımı etkilemez; yalnızca Protégé ve arayüz gösterimi içindir.

Adım 10 — Kaydet ve doğrula

public OWLOntology build() throws Exception { buildClasses(); buildObjectProperties(); buildDataProperties(); buildAllergiesAndAdditives(); buildProducts(); buildPersons(); buildRestrictions(); buildLabels(); System.out.println("Aksiyom: " + ont.getAxiomCount()); System.out.println("Mantiksal aksiyom: " + ont.getLogicalAxiomCount()); man.saveOntology(ont, new RDFXMLDocumentFormat(), IRI.create(new File("ALLERGY_GENERATED.owl").toURI())); return ont; }
Aksiyom: 121 Mantiksal aksiyom: 96

05

Okuma, Arama, Değiştirme

EntitySearcher, aksiyom filtreleri ve değişiklik yönetimi.

Envanter okuma

System.out.println("Sinif : " + ont.getClassesInSignature().size()); System.out.println("Nesne oz.: " + ont.getObjectPropertiesInSignature().size()); System.out.println("Veri oz. : " + ont.getDataPropertiesInSignature().size()); System.out.println("Birey : " + ont.getIndividualsInSignature().size());
  • Signature = ontolojide adı geçen bütün varlıklar.
  • getAxiomCount() ise aksiyom sayısıdır — ikisi farklı ölçüdür.
  • Bu dört satır, kodla üretilen dosyayı Protégé metrikleriyle karşılaştırmanın en hızlı yolu.
Sinif: 8  ·  Nesne oz.: 9  ·  Veri oz.: 6  ·  Birey: 17

EntitySearcher ile değer okuma

// Bir kisinin alerjileri EntitySearcher.getObjectPropertyValues(ind("TC_003"), op("hasAllergy"), ont) .forEach(v -> System.out.println(v)); // Bir kisinin adi (data property) EntitySearcher.getDataPropertyValues(ind("TC_003"), dp("hasName"), ont) .forEach(l -> System.out.println(l.getLiteral())); // Bir sinifin bildirilmis bireyleri EntitySearcher.getIndividuals(cls("Product"), ont) .forEach(i -> System.out.println(i.getIRI().getShortForm()));

Dikkat: EntitySearcher yalnızca bildirilmiş aksiyomları okur. Çıkarılan bilgi için reasoner gerekir (Hafta 09).

Aksiyom türüne göre arama

// Butun Contain bildirimleri ont.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION).stream() .filter(ax -> ax.getProperty().equals(op("Contain"))) .forEach(ax -> System.out.println( ax.getSubject() + " icerir " + ax.getObject())); // Bir sinifla ilgili tum aksiyomlar ont.getAxioms(cls("Person"), Imports.INCLUDED) .forEach(System.out::println); // SWRL kurallari System.out.println("Kural sayisi: " + ont.getAxioms(AxiomType.SWRL_RULE).size());
EAN_00004 icerir Nisin  ·  EAN_00003 icerir Casein  ·  …

Değişiklik yönetimi

// Toplu degisiklik listesi List<OWLOntologyChange> changes = new ArrayList<>(); changes.add(new AddAxiom(ont, df.getOWLClassAssertionAxiom( cls("Person"), ind("TC_005")))); changes.add(new RemoveAxiom(ont, df.getOWLObjectPropertyAssertionAxiom( op("Contain"), ind("EAN_00001"), ind("Alginic_Acid")))); List<OWLOntologyChange> applied = man.applyChanges(changes); System.out.println("Uygulanan degisiklik: " + applied.size());

Silme işleminde aksiyomun birebir aynı olması gerekir; literal tipi farklıysa silme sessizce başarısız olur ve applied boş döner.

Ontolojiyi nereden yükleyebilirsiniz?

// 1) Dosyadan man.loadOntologyFromOntologyDocument(new File("ALLERGY_FIXED.owl")); // 2) URL'den man.loadOntology(IRI.create("http://EMU/AllergyOntology")); // 3) Classpath icinden (jar ile paketlenmis) man.loadOntologyFromOntologyDocument( OntologyGateway.class.getResourceAsStream("/ALLERGY_FIXED.owl")); // 4) Metinden man.loadOntologyFromOntologyDocument( new StringDocumentSource(turtleText));

Import zinciri için AutoIRIMapper kullanın; aksi hâlde uzak import'lar internet erişimi gerektirir.

Sık hatalar ve tanısı

BelirtiNedenÇözüm
Boş sonuç, hata yokNS sonundaki # eksikNS sabitini denetle
Aksiyom sayısı artmıyorBaşka ontoloji nesnesine eklendiTek ont kullan
Kural boş dönüyorLiteral tipi stringgetOWLLiteral(38)
Silme çalışmıyorAksiyom birebir değilÖnce arayıp bulunanı sil
NoSuchMethodErrorOWL API 4/5 karışıkTek dala sabitle
Import bulunamadıUzak IRI erişilemezAutoIRIMapper

Ürettiğiniz dosyayı Protégé'de doğrulayın

ALLERGY_GENERATED.owl  ›  Ontology metrics
Metrics Axiom             121 Logical axiom      96 Class count        8 Object property    9 Data property      6 Individual         17
Class hierarchy ▾ owl:Thing ▾ Person Adult  · PersonAtRisk ▾ Product RiskyProduct (inferred) FoodAdditives  · Allergy

Şematik gösterim. Kodla üretilen dosya Protégé'de açılıp elle incelenebilir olmalıdır — bu, en hızlı doğrulama yöntemidir.

06

Ödev ve Proje Adımı

Ontolojinizi kodla üretin.

Ödev 8 — Programatik ontoloji

  1. Kendi ontolojinizi sıfırdan Java ile kurun (sınıf, özellik, birey, kısıt, etiket).
  2. Verileri koda gömmek yerine CSV'den okuyun; en az 20 ürün üretin.
  3. Envanter raporu yazdırın ve Protégé metrikleriyle karşılaştırın.
  4. Bir aksiyomu bulup silen ve doğrulayan bir metot yazın.
  5. Üretilen dosyayı Protégé'de açıp hiyerarşinin doğruluğunu gösterin.

Teslim

Maven projesi + CSV + üretilen .owl + konsol çıktısı + Protégé ekran görüntüleri.

Çözümü Hafta 09'un başında ele alacağız.

Değerlendirme ölçütleri

ÖlçütAğırlıkBeklenen
Kod yapısı20%Yardımcı metotlar, tekrar yok
Eleman kapsamı25%Sınıf, OTP, DTP, birey, kısıt, etiket
Literal tipleri15%int/double doğru
Veri kaynağından üretim20%CSV → ontoloji çalışıyor
Doğrulama20%Metrikler karşılaştırılmış

Kaynaklar ve referanslar

  • Horridge, M., Bechhofer, S. — The OWL API: A Java API for OWL Ontologies, Semantic Web Journal, 2011.
  • OWL API kaynak kodu ve örnekleri — github.com/owlcs/owlapi; wiki'deki "Examples" sayfası.
  • OWL API JavaDoc — OWLDataFactory ve OWLOntologyManager arayüzleri.
  • W3C — OWL 2 Structural Specification and Functional-Style Syntax (API'nin aksiyom modelinin kaynağı).
  • W3C — OWL 2 Primer; kısıt ve aksiyom türleri.
  • Horridge, M. — A Practical Guide To Building OWL Ontologies Using Protégé 5.
  • Glimm, B. et al. — HermiT: An OWL 2 Reasoner, Journal of Automated Reasoning, 2014.

Özet  •  1 / 2

API mimarisi

  • Manager dosya işlerini, data factory üretimi, ontology aksiyomları taşır.
  • Ontoloji sırasız, tekrarsız bir aksiyom kümesidir.
  • getOWLClass yalnızca referans üretir; ekleme addAxiom ile olur.
  • API aksiyom düzeyinde çalışır; blank node yönetimi sizden gizlenir.

Özet  •  2 / 2

Proje ve sonraki adım

  • Alerji ontolojisinin tamamı ~120 aksiyomla kodla üretilebiliyor.
  • Literal tipi, kuralların çalışmasının ön koşulu.
  • EntitySearcher yalnızca bildirilmiş bilgiyi okur.
  • Silme için aksiyom birebir eşleşmelidir.

Hafta 09'da

OWL API-II ve reasoner: HermiT/Pellet ile tutarlılık, sınıflandırma, gerçekleme ve çıkarımın kalıcı yazılması.

Ayrıca: Ödev 8'in ayrıntılı çözümü.

Tekrar Soruları

Kendinizi sınayın

  1. Neden düz RDF kütüphanesi yerine OWL API?
  2. getOWLClass ontolojiye ne ekler?
  3. Aksiyom kümesinin sırasız olması ne sağlar?
  4. DeclarationAxiom hangi durumda zorunludur?
  1. Literal tipi hatası kendini nasıl gösterir?
  2. EntitySearcher ile reasoner farkı nedir?
  3. Silme neden sessizce başarısız olur?
  4. AutoIRIMapper hangi sorunu çözer?

Alıştırma  •  Sınıf içi

Kodu tamamlayın

EAN_00005 (Protein Biscuit, Whey_Protein + Wheat_Starch) ontolojiye kodla eklenecek.

add(df.get________Axiom( cls("Product"), ind("EAN_00005"))); add(df.get________Axiom( op("Contain"), ind("EAN_00005"), ind("Whey_Protein"))); add(df.get________Axiom( op("Triggers"), ind("Whey_Protein"), ind("Lactose")));

Sorular

  1. Kaç aksiyom eklendi?
  2. Hangi kişi için S6 tetiklenir?
  3. Declaration aksiyomu gerekli mi?

Çözüm Hafta 09'da.